package com.albert.funny;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Locale;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.content.Context;
import android.location.Address;
//import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;

public class ReverseGeocoderProxy extends AsyncTask<Location, Void, String/*List<Address>*/>
{
    public static final int SUCCESS = 0;
    public static final int FAIL = 1;
    
    private Geocoder geocoder;
    private ReverseGeocoderProxyListener reverseGeocoderListener;
    public ReverseGeocoderProxy(Context context)
    {
       
        geocoder = new Geocoder();
    }

    @Override
    protected /*List<Address>*/String doInBackground(Location... params)
    {
//        List<Address> resultList = null;
        String address = "";
        if(params != null && params.length > 0)
        {
            double lat = params[0].getLatitude();
            double lon = params[0].getLongitude();
            if(lat != 0 && lon != 0)
            {
                    address = geocoder.reverseGeocode(params[0]);
                
            }
        }
        return address;
    }
    
    protected void onPostExecute (String result)
    {
        if (result != null)
        {
            int size = result.length();
            if(size > 0)
            {
                reverseGeocoderListener.reverseGeoCoderFinished(SUCCESS, result);
            }
            else
            {
                reverseGeocoderListener.reverseGeoCoderFinished(FAIL, null);
            }
        }
        else
        {
            reverseGeocoderListener.reverseGeoCoderFinished(FAIL, null);
        }
    }
    public void setGeocoderListener(ReverseGeocoderProxyListener listener)
    {
        this.reverseGeocoderListener = listener;
    }
    
    public interface ReverseGeocoderProxyListener
    {
        public void reverseGeoCoderFinished(int status, String adressString);
    }
}

class Geocoder 
{
    public static String reverseGeocode(Location loc)
    {
        //http://maps.google.com/maps/geo?q=40.714224,-73.961452&output=json&oe=utf8&sensor=true_or_false&key=your_api_key
        String localityName = "";
        HttpURLConnection connection = null;
        URL serverAddress = null;

        try 
        {
            // build the URL using the latitude & longitude you want to lookup
            // NOTE: I chose XML return format here but you can choose something else
            serverAddress = new URL("http://maps.google.com/maps/geo?q=" + Double.toString(loc.getLatitude()) + "," + Double.toString(loc.getLongitude()) +
                        "&output=xml&oe=utf8&sensor=true&key=" + R.string.GOOGLE_MAPS_API_KEY);
            //set up out communications stuff
            connection = null;
              
            //Set up the initial connection
            connection = (HttpURLConnection)serverAddress.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            connection.setReadTimeout(10000);
                          
            connection.connect();
            
            try
            {
                InputStreamReader isr = new InputStreamReader(connection.getInputStream());
                InputSource source = new InputSource(isr);
                SAXParserFactory factory = SAXParserFactory.newInstance();
                SAXParser parser = factory.newSAXParser();
                XMLReader xr = parser.getXMLReader();
                GoogleReverseGeocodeXmlHandler handler = new GoogleReverseGeocodeXmlHandler();
                
                xr.setContentHandler(handler);
                xr.parse(source);
                
                localityName = handler.getLocalityName();
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        
        return localityName;
    }
}

class GoogleReverseGeocodeXmlHandler extends DefaultHandler 
{
    private boolean inLocalityName = false;
    private boolean finished = false;
    private StringBuilder builder;
    private String localityName;
    
    public String getLocalityName()
    {
        return this.localityName;
    }
    
    @Override
    public void characters(char[] ch, int start, int length)
           throws SAXException {
        super.characters(ch, start, length);
//        System.out.println("characters:" + String.valueOf(ch));
        if (this.inLocalityName && !this.finished)
        {
            if ((ch[start] != '\n') && (ch[start] != ' '))
            {
                builder.append(ch, start, length);
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException 
    {
        super.endElement(uri, localName, name);
        
        if (!this.finished)
        {
            if (localName.equalsIgnoreCase("address"))
            {
                this.localityName = builder.toString();
                this.finished = true;
            }
            
            if (builder != null)
            {
                builder.setLength(0);
            }
        }
    }

    @Override
    public void startDocument() throws SAXException 
    {
        super.startDocument();
        builder = new StringBuilder();
    }

    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
    {
        super.startElement(uri, localName, name, attributes);
//        System.out.println("startElement:" + localName);
        if (localName.equalsIgnoreCase("address"))
        {
            this.inLocalityName = true;
        }
    }
}